package page

import "ibdreader/slice"

/**
 * InnoDB allocates FSP_HDR and XDES pages at fixed locations within the space.
 * 112 byte (38-150)
 */
type FspHeader struct {
	/** 该文件对应的space id. */
	Space int64

	/**
	 * Highest page number in file (size).
	 * <p>
	 * 当前表空间总的PAGE个数，扩展文件时需要更新该值fsp_try_extend_data_file_with_pages.
	 */
	Size int64

	/**
	 * Highest page number initialized (free limit).
	 * <p>
	 * 当前尚未初始化的最小Page No。从该Page往后的都尚未加入到表空间的FREE LIST上。
	 */
	FreeLimit int64

	/**
	 * 当前表空间的FLAG信息.
	 * <pre>
	 * Macro Desc
	 * FSP_FLAGS_POS_ZIP_SSIZE 压缩页的block size，如果为0表示非压缩表
	 * FSP_FLAGS_POS_ATOMIC_BLOBS 使用的是compressed或者dynamic的行格式
	 * FSP_FLAGS_POS_PAGE_SSIZE InnerPage Size
	 * FSP_FLAGS_POS_DATA_DIR 如果该表空间显式指定了data_dir，则设置该flag
	 * FSP_FLAGS_POS_SHARED 是否是共享的表空间，如5.7引入的General Tablespace，可以在一个表空间中创建多个表
	 * FSP_FLAGS_POS_TEMPORARY 是否是临时表空间
	 * FSP_FLAGS_POS_ENCRYPTION 是否是加密的表空间，MySQL 5.7.11引入
	 * FSP_FLAGS_POS_UNUSED 未使用的位
	 * </pre>
	 */
	Flags int64

	/** FSP_FREE_FRAG链表上已被使用的Page数，用于快速计算该链表上可用空闲Page数. */
	NumberOfPagesUsed int64

	/** 当一个Extent中所有page都未被使用时，放到该链表上，可以用于随后的分配. */
	Free ListBaseNode

	/**
	 * FREE_FRAG链表的Base Node，通常这样的Extent中的Page可能归属于不同的segment，
	 * 用于segment frag array page的分配.
	 */
	FreeFrag ListBaseNode

	/** Extent中所有的page都被使用掉时，会放到该链表上，当有Page从该Extent释放时，则移回FREE_FRAG链表. */
	FullFrag ListBaseNode

	/** 当前文件中最大Segment ID + 1，用于段分配时的seg id计数器. */
	NextUsedSegmentId int64

	/** 已被完全用满的Inode Page链表. */
	FullInodes ListBaseNode

	/** 至少存在一个空闲Inode Entry的Inode Page被放到该链表上. */
	FreeInodes ListBaseNode
}

func FspHeaderReadSlice() FspHeader {
	var fh FspHeader
	fh.Space = slice.ReadUnsignedInt()
	slice.SkipBytes(4)
	fh.Size = slice.ReadUnsignedInt()
	fh.FreeLimit = slice.ReadUnsignedInt()
	fh.Flags = slice.ReadUnsignedInt()
	fh.NumberOfPagesUsed = slice.ReadUnsignedInt()
	fh.Free = ListBaseNodefromSlice()
	fh.FreeFrag = ListBaseNodefromSlice()
	fh.FullFrag = ListBaseNodefromSlice()
	fh.NextUsedSegmentId = slice.ReadLongInt64()
	fh.FullInodes = ListBaseNodefromSlice()
	fh.FreeInodes = ListBaseNodefromSlice()
	return fh
}
